# Implementation of IValidate for all kinds of types



#class ValidateKey(IValidate)
#class ValidateBytes(IValidate)
#TODO: class ValidateList(IValidate)
#class ValidateDict(IValidate)
#class ValidateValue(IValidate)

#TODO: merge the Visitor into SingleOne

from bcat.util.type_checker import TypeChecker
from bcat.gtp.serde.dev2.ideserializer import IDeserializer
from bcat.gtp.serde.dev2.valid.ivalidate import IValidate
from bcat.gtp.serde.dev2.valid.ivalidator_visitor import IValidatorVisitor
from bcat.gtp.serde.dev2.imap_access import IMapAccess
from bcat.gtp.serde.dev2.iseq_access import ISeqAccess


class ValidateKey(IValidate):
    class Visitor(IValidatorVisitor): #same as Visitor
        def visit_key(self, s):
            return TypeChecker.is_bytes(s) and len(s) > 0

    def validate(self, deserializer) -> bool: #same as Deserialize::deserialize
        return deserializer.deserialize_key(ValidateKey.Visitor())

class ValidateBytes(IValidate):
    class Visitor(IValidatorVisitor):
        def visit_bytes(self, s):
            return TypeChecker.is_bytes(s) and len(s) > 0
    def validate(self, deserializer) -> bool:
        return deserializer.deserialize_bytes(ValidateBytes.Visitor())
    


class ValidateDict(IValidate):
    class VisitorDict(IValidatorVisitor): #same as Visitor
        def visit_dict(self, map_access):
            while map_access.has_next_entry():
                (k , v) = map_access.next_entry(ValidateKey, ValidateValue)
                if k == False or v == False: 
                    return False
            return True

    def validate(self, deserializer) -> bool: #same as Deserialize::deserialize
        return deserializer.deserialize_dict(ValidateDict.VisitorDict())

class ValidateValue(IValidate):
    class VisitorValue(IValidatorVisitor): #same as Visitor
        def visit_bytes(self, s):
            return TypeChecker.is_bytes(s) and len(s) > 0

        def visit_key(self, s):
            return TypeChecker.is_bytes(s) and len(s) > 0

        def visit_dict(self, map_access):
            while map_access.has_next_entry():
                (k , v) = map_access.next_entry(ValidateKey, ValidateValue)
                if k == False or v == False: 
                    return False
            return True
        def visit_list(self, seq_access):
            while seq_access.has_next_element():
                e = seq_access.next_element(ValidateValue)
                if e == False:
                    return False
            return True

    def validate(self, deserializer) -> bool: #same as Deserialize::deserialize
        return deserializer.deserialize_value(ValidateValue.VisitorValue())

#TODO: unittest 
